#include "Sem.hpp"
#include <vector>
#include "Lock.hpp"

namespace RingQueueModule
{
    using namespace MutexModule;
    using namespace SemModule;
    template <class T>
    class RingQueue
    {
    public:
        RingQueue(const RingQueue&) = delete;
        RingQueue& operator=(const RingQueue&) = delete;

        RingQueue(size_t capacity)
         :_cap(capacity)
         ,_ringqueue(_cap)
         ,_consumer(0)
         ,_producer(_cap)
         ,_constep(0)
         ,_prostep(0)
        {}

        void Equeue(T in)
        {
            _producer.P();
            _promutex.Lock();
            _ringqueue[_prostep++] = in;
            _prostep %= _cap;
            _promutex.Unlock();
            _consumer.V();
        }

        void Pop(T* out)
        {
            _consumer.P();
            _conmutex.Lock();
            *out = _ringqueue[_constep++];
            _constep %= _cap;
            _conmutex.Unlock();
            _producer.V();
        }
    private:
        size_t _cap; //环形队列容量
        std::vector<T> _ringqueue;   //环形队列
        
        //消费者生产者信号量
        Sem _consumer;
        Sem _producer;

        //消费者生产者位置下标
        size_t _constep;
        size_t _prostep;

        //线程安全引入两把锁
        Mutex _conmutex;
        Mutex _promutex;
    };
}